package com.qzyh.esb.egsa.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qzyh.esb.egsa.bean.bo.Sm2Key;
import com.qzyh.esb.egsa.bean.vo.ChangePwdVO;
import com.qzyh.esb.egsa.bean.vo.UserRoleAndDeptVO;
import com.qzyh.esb.egsa.bean.vo.UserSaveVO;
import com.qzyh.esb.egsa.bean.vo.UserVO;
import com.qzyh.esb.egsa.entity.*;
import com.qzyh.esb.egsa.mapper.*;
import com.qzyh.esb.egsa.service.IUserService;
import com.qzyh.esb.egsa.utils.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author whq
 * @since 2023-03-13
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

    @Value("${sm4Base64Str}")
    private String sm4Base64Str;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserDeptMapper userDeptMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private DeptMapper deptMapper;

    @Override
    public IPage<UserVO> getList(IPage<UserVO> page, String loginName) {
        return userMapper.selectUserList(page,loginName);
    }

    @Override
    public ResultObject saveUserInfo(UserSaveVO vo) {
        User user = new User();
        BeanUtils.copyProperties(vo,user);
        List<String> deptList = vo.getDeptList();
        List<String> roleList = vo.getRoleList();
        user = (User) FillUtil.fill(user);
        if(StringUtils.hasLength(user.getId())){
            userMapper.updateById(user);
            //修改用户信息时，先删除该用户关联的部门信息，后续重新插入。
            QueryWrapper<UserDept> userDeptQueryWrapper = Wrappers.query();
            userDeptQueryWrapper.eq("user_id", user.getId());
            userDeptMapper.delete(userDeptQueryWrapper);

            //修改用户信息时，先删除该用户关联的角色信息，后续重新插入。
            QueryWrapper<UserRole> userRoleQueryWrapper = Wrappers.query();
            userRoleQueryWrapper.eq("user_id", user.getId());
            userRoleMapper.delete(userRoleQueryWrapper);

        } else {
            user.setId(UuidUtil.getId());
            //初始密码设置为和登录名一致
            user.setLoginPwd(GmUtil.sm4Encrypt(sm4Base64Str,user.getLoginName()));
            userMapper.insert(user);
        }

        //如果所属部门集合不为空，则新增用户部门表
        if (deptList != null && deptList.size() >0)
            insertUserDept(deptList,user.getId());

        //如果关联角色集合不为空，则新增用户角色表
        if (roleList != null && roleList.size() >0)
            insertUserRole(roleList,user.getId());
        return ResultObject.success("保存成功");
    }

    @Override
    public ResultObject deleteById(String id) {
        //删除用户角色关联数据
        QueryWrapper<UserRole> userRoleQueryWrapper = Wrappers.query();
        userRoleQueryWrapper.eq("user_id", id);
        userRoleMapper.delete(userRoleQueryWrapper);

        //删除用户部门关联数据
        QueryWrapper<UserDept> userDeptQueryWrapper = Wrappers.query();
        userDeptQueryWrapper.eq("user_id", id);
        userDeptMapper.delete(userDeptQueryWrapper);
        //删除用户
        userMapper.deleteById(id);
        return ResultObject.success("删除成功");
    }

    @Override
    public ResultObject<UserRoleAndDeptVO> queryUserRoleAndDeptById(String id) {
        UserRoleAndDeptVO userRoleAndDeptVO = new UserRoleAndDeptVO();
        //查询用户部门关联数据
        QueryWrapper<UserDept> userDeptQueryWrapper = Wrappers.query();
        userDeptQueryWrapper.select("dept_id");
        userDeptQueryWrapper.eq("user_id", id);
        //查询该用户所属部门id
        List<UserDept> userDeptList = userDeptMapper.selectList(userDeptQueryWrapper);
        //所属部门id不为空
        if (userDeptList != null && userDeptList.size()>0){
            //提取部门id
            List<String> deptIdList = userDeptList.stream().map(UserDept::getDeptId).collect(Collectors.toList());
            //查询部门列表信息
            List<Dept> deptList = deptMapper.selectBatchIds(deptIdList);
            userRoleAndDeptVO.setDeptList(deptList);
        }

        //查询用户部门关联数据
        QueryWrapper<UserRole> userRoleQueryWrapper = Wrappers.query();
        userRoleQueryWrapper.select("role_id");
        userRoleQueryWrapper.eq("user_id", id);
        //查询该用户关联角色id
        List<UserRole> userRoleList = userRoleMapper.selectList(userRoleQueryWrapper);
        //关联角色id不为空
        if (userRoleList != null && userRoleList.size()>0){
            //提取角色id集合
            List<String> roleIdList = userRoleList.stream().map(UserRole::getRoleId).collect(Collectors.toList());
            //查询角色列表信息
            List<Role> roleList = roleMapper.selectBatchIds(roleIdList);
            userRoleAndDeptVO.setRoleList(roleList);
        }
        return ResultObject.success(userRoleAndDeptVO);
    }

    @Override
    public ResultObject changePwd(ChangePwdVO vo) {
        //获取用户id
        String userId = BaseContextUtil.getUserId();
        logger.info("用户id："+userId+"正在修改密码。。。");
        //获取旧密码密文
        String oldPwdCipher = vo.getOldPwd();
        //获取新密码密文
        String newPwdCipher = vo.getNewPwd();
        //获取确认密码密文
        String confirmPwdCipher = vo.getConfirmPwd();
        //密钥索引
        String keyId = vo.getKeyId();
        //获取密钥缓存
        Sm2Key sm2Key = new Sm2Key(CollectUtil.get("public"+keyId),CollectUtil.get("private"+keyId));
        //旧密码解密成明文
        String oldPwd = GmUtil.sm2Decrypt(sm2Key,oldPwdCipher);
        //新密码解密成明文
        String newPwd = GmUtil.sm2Decrypt(sm2Key,newPwdCipher);
        //确认密码解密成明文
        String confirmPwd = GmUtil.sm2Decrypt(sm2Key,confirmPwdCipher);

        //用 登录名+sm4加密后的密码 查询
        QueryWrapper<User> wrapper = Wrappers.query();
        wrapper.eq("id", userId);
        wrapper.eq("login_pwd", GmUtil.sm4Encrypt(sm4Base64Str,oldPwd));
        List<User> users = userMapper.selectList(wrapper);
        if (users!=null && users.size()==1){//查询数据不为空且只有一条，登录成功
            if(newPwd != null && newPwd.equals(confirmPwd)){
                User user = users.get(0);
                user.setLoginPwd(GmUtil.sm4Encrypt(sm4Base64Str,newPwd));
                user.setUpdateTime(LocalDateTime.now());
                //设置修改人员
                user.setUpdateUserId(BaseContextUtil.getUserId());
                userMapper.updateById(user);
                return ResultObject.success("修改密码成功");
            } else {
                logger.info(userId+"修改密码失败：新密码与确认密码不一致");
                return ResultObject.fail("新密码与确认密码不一致");
            }
        } else {//其余均为登录失败
            logger.info(userId+"修改密码失败：旧密码输入错误");
            return ResultObject.fail("旧密码输入有误");
        }
    }

    @Override
    public ResultObject resetPwd(String id) {
        User user = userMapper.selectById(id);
        user.setLoginPwd(GmUtil.sm4Encrypt(sm4Base64Str,user.getLoginName()));
        //设置修改时间
        user.setUpdateTime(LocalDateTime.now());
        //设置修改人员
        user.setUpdateUserId(BaseContextUtil.getUserId());
        userMapper.updateById(user);
        return ResultObject.success("重置密码成功");
    }

    private void insertUserRole(List<String> roleList, String id) {
        for (int i = 0; i < roleList.size(); i++) {
            UserRole userRole = new UserRole();
            userRole.setRoleId(roleList.get(i));
            userRole.setUserId(id);
            //设置创建时间
            userRole.setCreateTime(LocalDateTime.now());
            //设置创建人员
            userRole.setCreateUserId(BaseContextUtil.getUserId());
            userRoleMapper.insert(userRole);
        }
    }

    private void insertUserDept(List<String> deptList, String id) {
        for (int i = 0; i < deptList.size(); i++) {
            UserDept userDept = new UserDept();
            userDept.setDeptId(deptList.get(i));
            userDept.setUserId(id);
            //设置创建时间
            userDept.setCreateTime(LocalDateTime.now());
            //设置创建人员
            userDept.setCreateUserId(BaseContextUtil.getUserId());
            userDeptMapper.insert(userDept);
        }
    }

}
